Repository navigation
fix: three live rig-package defects (#701, #702, #703) - #706
Merged
Merged
Conversation
…runk
The `studio` component declared:
"path": "${env.HOMEBOY_RIG_COMPONENT_PATH__STUDIO_AGENT_CLAUDE_EVALTIMING__STUDIO}"
but the rig `id` is `studio-agent-claude-trunk`. Homeboy derives the
canonical override variable from `(rig_id, component_id)` in
`rig_component_path_override_env_name`
(crates/homeboy-rig/src/expand.rs:241-247), so the variable that actually
exists at runtime is `..._STUDIO_AGENT_CLAUDE_TRUNK__STUDIO`. The rig was
renamed from `studio-agent-claude-evaltiming` and this hand-written literal
was never updated, so the declared path was dead in every case:
- when the canonical override IS set, `resolve_component_path` returns it
first and unconditionally (component_resolution.rs:34), before `path` is
ever consulted; and
- when it is NOT set, `${env.…_EVALTIMING__STUDIO}` expands to the empty
string and resolution falls through to registry lookup.
Rather than correcting the literal, delete it. `path` is optional
(`#[serde(default, skip_serializing_if)]` on `ComponentSpec`) and the env
override already applies unconditionally, so the literal was pure
redundancy — and that redundancy is exactly what allowed the name to drift
undetected. Removing it makes the rename-safe path the only path.
No `path_setting` was present on this component, so nothing else to prune.
Behavior is unchanged in both the override-set and override-unset cases.
Swept every `HOMEBOY_RIG_COMPONENT_PATH__` literal in the repo against its
own rig id and component key; this was the only stale one. The remaining
literals are self-consistent (redundant, but correct).
Closes #701
…port shim The four Gutenberg workloads reported in #702 are NOT broken. Refuted by direct verification: `WordPress/gutenberg/shared/wp-codebox` is a symlink to `../../../shared/wp-codebox`, tracked in git as mode 120000 (blob 13d7ff0). So `../shared/wp-codebox/recipe.mjs` from `WordPress/gutenberg/bench/` resolves through that symlink to the repo-root `shared/wp-codebox/recipe.mjs`, which exists. Importing all four modules under node succeeds — each one runs to completion of its import graph and fails only on its runtime env guard ("HOMEBOY_COMPONENT_PATH is required"), which is proof the imports resolved. No change was made to those four files. The `../../../shared/...` form used by the woocommerce and studio workloads is the same target reached without the symlink hop; both are correct, and depth is not uniform (studio's `bench/lib/` correctly uses four levels). The repo-wide sweep that was supposed to confirm #702 did find one real broken import, unrelated to Gutenberg: WordPress/wordpress-develop/tools/fuzz-workload-validator.mjs:1 export { … } from './core-fuzz-contract-validator.mjs'; That target was deleted by 8ce2060 ("Consolidate WordPress rigs on Codebox primitives", #684), which removed the implementation but left this one-line re-export shim behind. Nothing in the repo imports the shim, so it is a dangling orphan whose only content is an unresolvable specifier. Deleted, along with the now-empty `tools/` directory. Sweep method: walked all 106 `.mjs`/`.js` files, extracted every relative `import`/`export … from`/dynamic `import()` specifier (138 total) and resolved each against the filesystem (following symlinks). After this change: 0 broken. Closes #702
… base
`woocommerce-wp-codebox-target.base.json` declared `"lifecycle"` twice — at
:2-7 and again at :65-69. `serde_json` is last-wins, so the second block
silently overwrote the first and the `"intent": "external"` declared in the
first was dropped from the materialized spec.
Merged into a single block at the original (first) position:
- `intent: "external"` is restored. It is declared exactly once across both
blocks, so there is no conflict on this field. It is also corroborated as
the deliberate value: `shared/wordpress-plugin/wp-codebox-external-cleanup.base.json`
contains the first block verbatim, so that block was copy-pasted from the
shared external-cleanup base — and this file is itself named
`…-wp-codebox-target.base.json`.
- The `reason` is taken from the SECOND block. The two differ only in
specificity ("component checkouts are user-owned" vs. "the WooCommerce
component checkout is user-owned"); the second is the local refinement and
is the string that is actually in effect on main today, so keeping it means
the human-readable text does not regress.
Runtime impact is nil, which is why this went unnoticed:
`RigCleanupSpec::resource_cleanup_intent` maps both `External` and an absent
`intent` to `ResourceCleanupIntent::DryRun` (crates/homeboy-rig/src/spec.rs),
and `RigCleanupIntent` is not consumed anywhere else in homeboy. So the
dropped field was declarative/documentary rather than behavioral. Restoring
it makes the declared cleanup ownership survive into the materialized spec
without changing what cleanup actually does.
Swept all 160 JSON files in the repo with `json.load` under an
`object_pairs_hook` that flags repeated keys at every nesting level. This was
the only file affected; after this change the sweep reports 0.
Closes #703
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes three reported rig-package defects. One of the three (#702) is refuted — the reported files are not broken, but the sweep it prompted found a different, real defect. Details below.
Found during the 2026-08-01 consolidation investigation (Extra-Chill/homeboy#11151).
#701 — stale rig-id env literal (CONFIRMED)
Automattic/studio/rigs/studio-agent-claude-trunk/rig.jsondeclared:while the rig
idisstudio-agent-claude-trunk. Homeboy derives the canonical override name from(rig_id, component_id)inrig_component_path_override_env_name(crates/homeboy-rig/src/expand.rs:241-247), so the variable that exists at runtime is..._STUDIO_AGENT_CLAUDE_TRUNK__STUDIO. The rig was renamed fromstudio-agent-claude-evaltimingand the hand-written literal was never updated.The literal was dead in both directions:
resolve_component_pathreturns it first and unconditionally (component_resolution.rs:34) — beforepathis consulted at all;${env.…_EVALTIMING__STUDIO}expands to the empty string and resolution falls through to registry lookup.Fix: deleted the literal rather than correcting it.
pathis optional (#[serde(default, skip_serializing_if)]onComponentSpec) and the env override already applies unconditionally, so it was pure redundancy — and that redundancy is precisely what let the name drift undetected. Nopath_settingwas present on this component. Behavior is unchanged in both cases.#702 — Gutenberg imports (REFUTED — but the sweep found a real one)
The four reported Gutenberg workloads are not broken.
WordPress/gutenberg/shared/wp-codeboxis a symlink to../../../shared/wp-codebox, tracked in git as mode120000(blob13d7ff06). So../shared/wp-codebox/recipe.mjsfromWordPress/gutenberg/bench/resolves through that symlink to the repo-rootshared/wp-codebox/recipe.mjs, which exists.Verified by actually importing all four under node: each runs its import graph to completion and fails only on its runtime env guard (
HOMEBOY_COMPONENT_PATH is required), which proves the imports resolved. No change made to those four files.Also worth noting the premise that "correct depth is three levels" is not universal —
Automattic/studio/bench/lib/visual-fidelity.mjscorrectly uses four (../../../../shared/...), because depth depends on the file's own location. Any future lint rule must resolve, not pattern-match.The sweep did find one genuinely unresolvable import, unrelated to Gutenberg:
That target was deleted by 8ce2060 ("Consolidate WordPress rigs on Codebox primitives", #684), which removed the implementation but left this one-line re-export shim behind. Nothing in the repo imports the shim — it is a dangling orphan whose entire content is an unresolvable specifier. Deleted, along with the now-empty
tools/directory.#703 — duplicate
lifecyclekey (CONFIRMED)woocommerce/woocommerce/rigs/woocommerce-performance/woocommerce-wp-codebox-target.base.jsondeclared"lifecycle"twice (:2-7and:65-69).serde_jsonis last-wins, so the second block silently overwrote the first and"intent": "external"was dropped from the materialized spec.Merged into a single block at the original (first) position:
intent: "external"restored. It is declared exactly once across both blocks, so there is no conflict on this field.reasontaken from the second block. The two differ only in specificity ("component checkouts are user-owned" vs. "the WooCommerce component checkout is user-owned"). The second is the local refinement and is the string actually in effect onmaintoday, so the human-readable text does not regress.On the ambiguity
It is low, and here is the evidence rather than a guess:
shared/wordpress-plugin/wp-codebox-external-cleanup.base.jsoncontains the first block verbatim, so that block was copy-pasted from the shared external-cleanup base — and this file is itself named…-wp-codebox-target.base.json.externalis the house pattern for exactly this kind of target. The only field that had to be adjudicated wasreason, and there I kept the currently-effective string.Runtime impact is nil, which is worth stating plainly so this is not mistaken for a behavior change in cleanup:
RigCleanupSpec::resource_cleanup_intentmaps bothExternaland an absentintenttoResourceCleanupIntent::DryRun(crates/homeboy-rig/src/spec.rs), andRigCleanupIntentis not consumed anywhere else in homeboy. The dropped field was declarative/documentary. Restoring it makes declared cleanup ownership survive into the materialized spec without changing what cleanup does.Why CI did not catch these
homeboy rig lintfollows filenames rather than the materialized spec, and has no import resolution — tracked upstream as Extra-Chill/homeboy#11148. Demonstrated directly againstorigin/mainwith the defects still present:homeboy rig lint woocommerce/woocommerce --all→ 0 failures with the duplicatelifecyclekey in place. The "rig package JSON specs parse" step passes becauseserde_jsonaccepts duplicates by design (last-wins); nothing compares the parsed spec against the source text..mjsimport specifiers, so the orphaned shim was invisible.HOMEBOY_RIG_COMPONENT_PATH__…literal against the rig's ownid, so theEVALTIMING/TRUNKdrift was invisible.Repo-wide sweeps
All three defect classes were swept exhaustively, not just the reported instances.
rig.json, resolvedextendschains to attribute base files to their consuming rig ids, recomputedsanitize_env_segment(rig_id)__sanitize_env_segment(component_id)and compared to everyHOMEBOY_RIG_COMPONENT_PATH__literalstudio-agent-claude-trunk) — fixed. All other literals self-consistent..mjs/.js, extracted every relativeimport/export … from/ dynamicimport()specifier (138 total), resolved each against the filesystem following symlinksfuzz-workload-validator.mjs) — fixed. Now 0 broken.json.loadwith anobject_pairs_hookflagging repeats at every nesting level, across all 160 JSON fileswoocommerce-wp-codebox-target.base.json) — fixed. Now 0.Follow-up worth considering (not changed here)
Every remaining
"path": "${env.HOMEBOY_RIG_COMPONENT_PATH__<SELF>__<COMP>}"literal in the repo is self-consistent but equally redundant, for the same reason as #701: the override is applied unconditionally ahead ofpath, and absent the env var the literal expands to empty and falls through to registry lookup. They are correct today and are left alone, but they are the same drift hazard. Worth a follow-up to prune them, ideally alongside a lint rule from Extra-Chill/homeboy#11148.Validation
python3 -m json.tool); duplicate-key sweep clean..mjspassnode --check; import sweep reports 0 broken.homeboy rig lint --allonwoocommerce/woocommerce,WordPress/wordpress-develop,WordPress/gutenberg: 0 failures.Automattic/studioreports 1 failure (RigCleanupSpecuntagged-enum schema skew) — pre-existing and identical onorigin/main, verified by linting a cleanorigin/mainextract with the same binary (v0.327.0). Not introduced here.cargoinvoked.